package com.xbongbong.paas.handle;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.pro.weblist.pojo.ListOptionPackagePojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ProductUnitPriceEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.SupplierProductEntity;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.enums.ListOptionEnum;
import com.xbongbong.saas.enums.ListOptionTabEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.help.ProductListHelp;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.help.SaasListHelp;
import com.xbongbong.saas.model.ProductUnitPriceModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.SupplierProductModel;
import com.xbongbong.saas.service.ProductService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 产品操作
 * @author lee
 * @version v1.0
 * @date 2020/3/31 11:23
 * @since v1.0
 */
@Component
public class ProductOptionHandle extends AbstractOptionHandle {

    @Resource
    private SaasListHelp saasListHelp;
    @Resource
    private EsHelper esHelper;
    @Resource
    private SupplierProductModel supplierProductModel;
    @Resource
    private ProductListHelp productListHelp;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private ProductUnitPriceModel productUnitPriceModel;
    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private ProductService productService;

    @Override
    public void setOptionsInExplain(FormDataListDTO formDataListDTO, List<FieldAttrEntity> explainList, PaasFormDataEsListVO paasFormDataEsListVO) throws XbbException {
        // 获取按钮的开关
        ListOptionPackagePojo listOptionPackagePojo = getListOption(formDataListDTO, paasFormDataEsListVO);
        // 拼装表头
        saasListHelp.setHeadList(explainList, listOptionPackagePojo, formDataListDTO.getSubBusinessType() , formDataListDTO.getBusinessType());
        // 去掉子表单标题头，实际上可以加在HandleExplainHelp.handleExplain中，但是避免对其他业务造成影响，先写在这里，如果全部列表改造的话，可统一改到HandleExplainHelp.handleExplain中
        removeSubFormItems(explainList, formDataListDTO.getBusinessType());
    }

    @Override
    public ListOptionPackagePojo getFirstOptionData(FormDataListDTO formDataListDTO, PaasFormDataEsListVO paasFormDataEsListVO) throws XbbException {
        return new ListOptionPackagePojo();
    }

    private ListOptionPackagePojo getListOption(FormDataListDTO formDataListDTO, PaasFormDataEsListVO paasFormDataEsListVO) throws XbbException {
        ListOptionPackagePojo listOptionPackagePojo = new ListOptionPackagePojo();
        Integer subBusinessType = formDataListDTO.getSubBusinessType();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(subBusinessType);
        switch (xbbRefTypeEnum) {
            case PRODUCT:
                listOptionPackagePojo.setOnline(true);
                listOptionPackagePojo.setProductExplainMap(formDataListDTO.getExplainMap());
                FieldAttrEntity specAttr = formDataListDTO.getExplainMap().get(ProductEnum.SPECIFICATION.getAttr());
                if (Objects.nonNull(specAttr) && Objects.equals(specAttr.getVisible(),1) && Objects.equals(specAttr.getIsOpen(),1)) {
                    listOptionPackagePojo.setNeedOption7(true);
                }
                List<PaasFormDataEntityExt> list = paasFormDataEsListVO.getPaasFormDataESList();
                for (PaasFormDataEntityExt entity : list){
                    JSONObject data = entity.getData();
                    Integer specMode = data.getInteger(ProductEnum.SPECIFICATION.getAttr());
                    data.remove(ProductEnum.PRICE.getAttr());
                    data.remove(ProductEnum.COST.getAttr());
                    data.remove(ProductEnum.SPECIFICATION.getAttr());
                    data.remove(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                    data.remove(ProductEnum.SUPPLIER.getAttr());
                    data.remove(ProductEnum.SUPPLIER_LINK_TEXT.getAttr());
                    data.remove(ProductEnum.STOCK.getAttr());
                    if (listOptionPackagePojo.getNeedOption0()) {
                        // 库存查询列表页没有操作按钮
                        JSONObject option = new JSONObject();
                        List<ButtonPojo> buttonPojoList = ButtonPojo.deepClone(listOptionPackagePojo.getOptionList());
                        if (listOptionPackagePojo.getOnline()) {
                            buttonPojoList.add(Objects.equals(data.getInteger(ProductEnum.ONLINE.getAttr()), 1) ? new ButtonPojo(ListOptionTabEnum.OFFLINE) : new ButtonPojo(ListOptionTabEnum.ONLINE));
                            option.put("value", buttonPojoList);
                        } else if (listOptionPackagePojo.getProductionOrderFinish()) {
                            buttonPojoList.add(Objects.equals(data.getInteger(ProductionOrderEnum.STATUS.getAttr()), 1) ? new ButtonPojo(ListOptionTabEnum.FINISH) : new ButtonPojo(ListOptionTabEnum.RESTART));
                            option.put("value", buttonPojoList);
                        } else {
                            option.put("value", buttonPojoList);
                        }
                        data.put(ListOptionEnum.OPTION.getAttr(), option);
                    }
                    if (listOptionPackagePojo.getNeedOption7()) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("advancedMode", specMode);
                        jsonObject.put("value", new JSONObject());
                        jsonObject.put("tableHead", new JSONArray());
                        data.put(ListOptionEnum.MULTI_SPEC.getAttr(), jsonObject);
                    }
                }
                break;
            case GUARANTEE_SEARCH:
                break;
            case STOCK_SEARCH:
                break;
            case WARNING_SEARCH:
                break;
            default:
                break;
        }
        return listOptionPackagePojo;
    }


    @Override
    public void setOptionsInData(FormDataListDTO formDataListDTO, PaasFormDataEsListVO paasFormDataEsListVO) throws XbbException {
        List<Long> dataIdList = formDataListDTO.getIdIn();
        HashSet<Long> multiUnitIdList = new HashSet<>();
        // 查询子产品
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", formDataListDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery("formId", formDataListDTO.getFormId()));
        boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termsQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), dataIdList));
        List<String> fieldList = Arrays.asList(FieldTypeEnum.DATAID.getAlias(), ProductEnum.getAttrConnectData(ProductEnum.COST), ProductEnum.getAttrConnectData(ProductEnum.PRICE),
                ProductEnum.getAttrConnectData(ProductEnum.SPECIFICATION), ProductEnum.getAttrConnectData(ProductEnum.SPECIFICATION_LINK_TEXT), ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID),  ProductEnum.getAttrConnectData(ProductEnum.BARCODE),  ProductEnum.getAttrConnectData(ProductEnum.ENABLE_MULTI_UNIT));
        List<ProductEntityExt> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, ProductEntityExt.class, fieldList);
        List<Long> childIdList = new ArrayList<>(childProductList.size());
        childProductList.forEach(item -> childIdList.add(item.getDataId()));
        Map<Long, List<ProductWarehouseEntity>> productWarehouseMap =  productWarehouseModel.getWarehouseProductMap(formDataListDTO.getCorpid(), childIdList, Arrays.asList(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr(StringConstant.PARENTID), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr(ParameterConstant.WAREHOUSE_ID), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("productId"), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("cost"), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("num")));
        Map<Long, JSONArray> childProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        childProductList.forEach(item -> {
            Long parentId = item.getData().getLong(ProductEnum.PARENT_ID.getAttr());
            Long dataId = item.getDataId();
            JSONArray childList = childProductMap.getOrDefault(parentId, new JSONArray());
            JSONObject childObject = new JSONObject();
            childObject.put(ProductEnum.COST.getSaasAttr(), item.getData().get(ProductEnum.COST.getAttr()));
            childObject.put(ProductEnum.PRICE.getSaasAttr(), item.getData().get(ProductEnum.PRICE.getAttr()));
            childObject.put(ProductEnum.BARCODE.getSaasAttr(), item.getData().get(ProductEnum.BARCODE.getAttr()));
            childObject.put(ProductEnum.SPECIFICATION.getSaasAttr(), item.getData().get(ProductEnum.SPECIFICATION.getAttr()));
            childObject.put(ProductEnum.SPECIFICATION_LINK_TEXT.getSaasAttr(), item.getData().get(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            if (productWarehouseMap.containsKey(dataId)) {
                Double stock = 0D;
                for (ProductWarehouseEntity productWarehouseEntity : productWarehouseMap.get(dataId)) {
                    if (!Objects.equals(productWarehouseEntity.getWarehouseId(), 0L)) {
                        stock = Arith.add(stock, productWarehouseEntity.getNum());
                    }
                }
                childObject.put(ProductEnum.STOCK.getSaasAttr(), stock);
            } else {
                childObject.put(ProductEnum.STOCK.getSaasAttr(), 0D);
            }
            childList.add(childObject);
            childProductMap.put(parentId, childList);
            if (Objects.equals(item.getData().getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)) {
                multiUnitIdList.add(parentId);
            }
        });
        Map<Long, JSONArray> multiProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //查询多单位产品价格
        if (!multiUnitIdList.isEmpty()) {
            ProductFieldPojo productFieldPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), formDataListDTO.getCorpid());
            Map<Long, List<UnitItemPoJo>> groupMap = productFieldPojo.getMultiItems().stream().collect(Collectors.toMap(MultiUnitItemPoJo::getValue, MultiUnitItemPoJo::getItemDataPoJoList));
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
            params.put(ParameterConstant.DEL, 0);
            params.put("parentIdIn", multiUnitIdList);
            List<ProductUnitPriceEntity> entitys = productUnitPriceModel.findEntitys(params);
            for (ProductUnitPriceEntity entity : entitys) {
                Long parentId = entity.getParentId();
                JSONArray childList = multiProductMap.getOrDefault(parentId, new JSONArray());
                JSONArray price = entity.getPrice();
                List<UnitItemPoJo> unitItemPoJos = groupMap.getOrDefault(entity.getUnitGroupId(), new ArrayList<>());
                if (unitItemPoJos.size() != price.size()){
                    price = productService.formatMultiPrice(unitItemPoJos, price);
                }
                for (int i = 0; i < price.size(); i++) {
                    JSONObject child = (JSONObject) price.get(i);
                    child.put(ProductEnum.PRICE.getSaasAttr(), child.getDoubleValue(BasicConstant.RATE));
                    childList.add(child);
                }
                multiProductMap.put(parentId, childList);
            }
        }
        // 查询供应商
        Map<Long, List<SupplierProductEntity>> supplierProductMap = supplierProductModel.getSupplierProductByParentIdIn(formDataListDTO.getCorpid(), dataIdList, true);
        Map<String, FieldAttrEntity> productExplainMap = new HashMap<>(paasFormDataEsListVO.getHeadList().size());
        paasFormDataEsListVO.getHeadList().forEach(item-> {
            productExplainMap.put(item.getAttr(), item);
        });

        FieldAttrEntity priceField = productExplainMap.get(ProductEnum.PRICE.getAttr());
        FieldAttrEntity costField = productExplainMap.get(ProductEnum.COST.getAttr());
        FieldAttrEntity supplierField = productExplainMap.get(ProductEnum.SUPPLIER.getAttr());
        FieldAttrEntity stockField = productExplainMap.get(ProductEnum.STOCK.getAttr());
        FieldAttrEntity barcodeField = productExplainMap.get(ProductEnum.BARCODE.getAttr());
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEsListVO.getPaasFormDataESList()) {
            JSONObject product = paasFormDataEntityExt.getData();
            JSONArray value = childProductMap.get(paasFormDataEntityExt.getDataId()) == null ? new JSONArray() : childProductMap.get(paasFormDataEntityExt.getDataId());
            if (priceField != null && (Objects.isNull(priceField.getHasJudgeVisible())) && Objects.equals(priceField.getIsOpen(), 1) && multiUnitIdList.contains(paasFormDataEntityExt.getDataId())) {
                JSONArray priceValue = multiProductMap.get(paasFormDataEntityExt.getDataId());
                if (Objects.nonNull(priceValue) && !priceValue.isEmpty()) {
                    productListHelp.setParentPrice(product, priceValue, priceField);
                }
            } else if (priceField != null && (Objects.isNull(priceField.getHasJudgeVisible())) && Objects.equals(priceField.getIsOpen(), 1)) {
                productListHelp.setParentPrice(product, value, priceField);
            } else {
                if (Objects.nonNull(priceField)) {
                    product.remove(priceField.getAttr());
                }
            }
            if (costField != null && Objects.isNull(costField.getHasJudgeVisible()) && Objects.equals(costField.getIsOpen(), 1)) {
                productListHelp.setParentPrice(product, value, costField);
            } else {
                if (Objects.nonNull(costField)) {
                    product.remove(costField.getAttr());
                }
            }
            if (supplierField != null && Objects.isNull(supplierField.getHasJudgeVisible()) && Objects.equals(supplierField.getIsOpen(), 1)) {
                productListHelp.setProductSupplier(product, supplierProductMap.get(paasFormDataEntityExt.getDataId()), costField);
            } else {
                if (Objects.nonNull(supplierField)) {
                    product.remove(supplierField.getAttr());
                }
            }
            if (barcodeField != null && Objects.isNull(barcodeField.getHasJudgeVisible()) && Objects.equals(barcodeField.getIsOpen(), 1) && value.size() == 1) {
                product.put(ProductEnum.BARCODE.getAttr(), value.getJSONObject(0).getString(ProductEnum.BARCODE.getSaasAttr()));
            } else {
                if (Objects.nonNull(barcodeField)) {
                    product.remove(barcodeField.getAttr());
                }
            }
            if (stockField != null && Objects.isNull(stockField.getHasJudgeVisible()) && Objects.equals(stockField.getIsOpen(), 1)) {
                Double allStock = 0D;
                for (int i = 0; i < value.size(); i++) {
                    JSONObject jsonObject = value.getJSONObject(i);
                    Double stock = jsonObject.getDouble(ProductEnum.STOCK.getSaasAttr());
                    allStock = Arith.add(allStock, stock);
                }
                product.put(stockField.getAttr(), allStock);
            } else {
                if (Objects.nonNull(stockField)) {
                    product.remove(stockField.getAttr());
                }
            }
            if (Objects.equals(product.getInteger(ProductEnum.SPECIFICATION.getAttr()),1)){
                product.put(ProductEnum.SPECIFICATION.getAttr(),value.size() + "个规格");
            } else {
                if (value.size() > 0) {
                    product.put(ProductEnum.SPECIFICATION.getAttr(), value.getJSONObject(0).getString(ProductEnum.SPECIFICATION_LINK_TEXT.getSaasAttr()));
                } else {
                    product.put(ProductEnum.SPECIFICATION.getAttr(), "");
                }
            }
        }
    }
}
